﻿/*
 * This software is the confidential and proprietary
 * information of NetBay
 * Such confidential information should not be disclosed
 * NetBay copyright(c) 2010
 */

#region Using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using NetBay.Core.BusinessEntities;
using NetBay.Core.DataAccess;
using NetBay.Core.Log;
using Rio.Doc.Business.Repository.Translator;
using NetBay.Core.BusinessEntities.AdvancedSearchCriteria;
using Rio.Doc.DataAccess;
#endregion

namespace Rio.Doc.Business.Repository
{
    /// <summary>
    /// Folder type Repository
    /// </summary>
    public class FolderTypeRepository : FolderTypeDer
    {
        /// <summary>
        /// Returns all Document Types from an Organization
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="organizationId">Organisation ID</param>
        /// <returns>
        /// The list of all document types attached to this Organization
        /// </returns>
        public static List<FolderType> GetFolderTypeByOrganization(long userId, long organizationId)
        {
            return FolderTypeTranslator.TranslateFolderType(userId, DA_FolderType.GetFolderTypeByOrganization(userId, organizationId));
        }

        /// <summary>
        /// Return all folders that match with regular expression applied to item's value
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="criteriaFilter">Association of regular expression and items</param>
        /// <returns>
        /// The cuple of folders filtered and all folders
        /// </returns>
        public Tuple<List<Folder>, List<Folder>> GetFoldersFilteredByRegularExpressionIntoItems(long userId, Dictionary<long, string> criteriaFilter = null)
        {
            SetFolderList(userId, criteriaFilter);
            return Tuple.Create(LstFolders, LstFoldersInternal);
        }

        /// <summary>
        /// Gets the folders filtered by regular expression into items for advanced search.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="criteriaFilter">The criteria filter.</param>
        /// <returns></returns>
        public Tuple<List<Folder>, List<Folder>> GetFoldersFilteredByRegularExpressionIntoItemsForAdvancedSearch(long userId, List<AdvancedSearchCriteriaItem> criteriaFilter)
        {
            SetFolderList(userId, criteriaFilter);
            return Tuple.Create(LstFolders, LstFoldersInternal);
        }


        /// <summary>
        /// Gets the folder by folder id.
        /// </summary>
        /// <param name="folderId">The folder id.</param>
        /// <param name="folderIdentifier">The folder identifier.</param>
        /// <returns></returns>
        public Folder GetFolderByFolderId(long folderId, string folderIdentifier = "")
        { 
            Folder l_oRet = new Folder();

            try
            {
                // Retreives the Folder for one FolderType
                List<Folder> l_oFolders = FolderTranslator.TranslateFolder(DA_Folder.GetFolderByFolderId(Identifier, folderId, folderIdentifier), LstIndex, Table);
                if (l_oFolders != null) l_oRet = l_oFolders.First();
            }
            catch (Exception ex)
            {
                l_oRet = new Folder("(p_lFolderId<" + folderId + ">)", ex);
                LogManager.Instance().LogError(l_oRet.FullErrorMessage);
            }
            return l_oRet;
        }

        /// <summary>
        /// Gets the folder by folder ids.
        /// </summary>
        /// <param name="folderIds">The folder ids.</param>
        /// <param name="folderIdentifier">The folder identifier.</param>
        /// <returns></returns>
        public List<Folder> GetFolderByFolderIds(string folderIds, string folderIdentifier = "")
        {
            List<Folder> l_oFolders;

            try
            {
                // Retreives the Folder for one FolderType
                l_oFolders = FolderTranslator.TranslateFolder(DA_Folder.GetFolderByFolderIds(Identifier, folderIds, folderIdentifier), LstIndex, Table, true);

            }
            catch (Exception ex)
            {
                l_oFolders = new List<Folder>();
                Folder l_oFolder = new Folder("(p_lFolderId<" + folderIds + ">)", ex);
                l_oFolders.Add(l_oFolder);
                LogManager.Instance().LogError(l_oFolder.FullErrorMessage);
            }
            return l_oFolders;
        }

        /// <summary>
        /// Sets the index list.
        /// </summary>
        /// <param name="userId">The user id.</param>
        public override void SetIndexList(long userId)
        {
            LstIndex = IndexRepository.GetIndexByFolderType(userId, Identifier);
        }

        /// <summary>
        /// Sets the index list.
        /// </summary>
        /// <param name="userId">The user id.</param>
        public override void SetIndexList()
        {
            LstIndex = IndexRepository.GetIndexByFolderType(Identifier);
        }

        /// <summary>
        /// Sets the group list.
        /// </summary>
        public override void SetGroupList()
        {
            AttachedGroups = GetFolderTypeGroups(this.Identifier);
        }

        /// <summary>
        /// Sets the folder list.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="criteriaFilter">The criteria filter.</param>
        public override void SetFolderList(long userId, Dictionary<long, string> criteriaFilter = null)
        {
            var l_oAllFolders = FolderRepository.GetFolderByFolderTypeId(userId, Identifier, LstIndex, Table, criteriaFilter);
            LstFolders = l_oAllFolders;
            LstFoldersInternal = null;
        }

        /// <summary>
        /// Overrided Method from the base class
        /// </summary>
        /// <param name="userId">The P_L user id.</param>
        /// <param name="criteriaFilter">The p_o criteria filter.</param>
        public override void SetFolderList(long userId, List<AdvancedSearchCriteriaItem> criteriaFilter)
        {
            var l_oAllFolders = FolderRepository.GetFolderByFolderTypeIdForAdvancedSearch(userId, Identifier, LstIndex, Table, criteriaFilter);
            LstFolders = l_oAllFolders;
            LstFoldersInternal = null;
        }

        /// <summary>
        /// Gets the folder type repository.
        /// </summary>
        /// <param name="userId">The P_L user id.</param>
        /// <param name="organisationId">The P_L organisation id.</param>
        /// <param name="folderTypeId">The P_L folder type id.</param>
        /// <param name="foldertypeRepository">The p_o foldertype repository.</param>
        public static void GetFolderTypeRepository(long userId, long organisationId, long folderTypeId, out FolderTypeRepository foldertypeRepository)
        {
            foldertypeRepository = null;
            OrganizationRepository l_oOrganisation = null;

            GetOrganisationRepository(userId, organisationId, out l_oOrganisation);
            foldertypeRepository = (FolderTypeRepository)l_oOrganisation.FolderTypesList.Find(item => item.Identifier == folderTypeId);

            // Check if the FolderType is founded
            if (foldertypeRepository == null)
            {
                throw new Exception("FolderType(" + folderTypeId + ") in Organisation(" + organisationId + ") not found");
            }
        }

        /// <summary>
        /// Gets the organisation repository.
        /// </summary>
        /// <param name="userId">The P_L user id.</param>
        /// <param name="organisationId">The P_L organisation id.</param>
        /// <param name="organisationRepository">The p_o organisation repository.</param>
        public static void GetOrganisationRepository(long userId, long organisationId, out OrganizationRepository organisationRepository)
        {
            organisationRepository = null;
            var OrganizationList = OrganizationRepository.GetAllRioOrganization();
            organisationRepository = (OrganizationRepository)OrganizationList.Find(item => item.Identifier == organisationId);

            // Check if the Organisation is founded
            if (organisationRepository == null)
            {
                throw new Exception("Organisation(" + organisationId + ") not found");
            }

            //Getting the Document type
             organisationRepository.SetFolderTypeList(userId);
        }

        /// <summary>
        /// Sets the item list.
        /// </summary>
        /// <param name="userId">The user id.</param>
        [STAThread]
        public override void SetItemList(long userId)
        {
            try
            {
                LstItems = ItemRepository.GetItemByFolderType(userId, Identifier);

                var l_oDocument = new XDocument( 
                    new XDeclaration("1.0", "utf-8", "yes"),
                    new XComment("Generate at :" + DateTime.Now.ToLongDateString()),
                    new XElement("Root")
                    );

                foreach (Item l_oItem in LstItems)
                {
                    BuildTreeItem(GetXElementsFromNodes(l_oDocument).First(), l_oItem.Code, l_oItem.Code, l_oItem.Name);
                }

                TreeNodeForItem = l_oDocument.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to SetItemList for UserId(" + userId + ")", ex);
            }
        }

        /// <summary>
        /// Gets the X elements from nodes.
        /// </summary>
        /// <param name="p_oXElement">The p_o X element.</param>
        /// <returns></returns>
        private IEnumerable<XElement> GetXElementsFromNodes(XElement p_oXElement)
        {
            return from item in p_oXElement.Nodes()
                   where item is XElement
                   select (XElement)item;
        }
        /// <summary>
        /// Gets the X elements from nodes.
        /// </summary>
        /// <param name="p_oXDocument">The p_o X document.</param>
        /// <returns></returns>
        private IEnumerable<XElement> GetXElementsFromNodes(XDocument p_oXDocument)
        {
            return from item in p_oXDocument.Nodes()
                   where item is XElement
                   select (XElement)item;
        }

        /// <summary>
        /// Gets the X element from nodes.
        /// </summary>
        /// <param name="p_oXElement">The p_o X element.</param>
        /// <param name="p_iIndex">Index of the p_i.</param>
        /// <returns></returns>
        private XElement GetXElementFromNodes(XElement p_oXElement, int p_iIndex)
        {
            XElement l_oRet;
            try
            {
                l_oRet = GetXElementsFromNodes(p_oXElement).ElementAt(p_iIndex);
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to search Index(" + p_iIndex + ") in XElement(" + p_oXElement + ")", ex);
            }
            return l_oRet;
        }

        /// <summary>
        /// Builds the tree item.
        /// </summary>
        /// <param name="p_oXElementParent">The p_o X element parent.</param>
        /// <param name="p_szCode">The P_SZ code.</param>
        /// <param name="p_szFullCode">The P_SZ full code.</param>
        /// <param name="p_szName">Name of the P_SZ.</param>
        private void BuildTreeItem(XElement p_oXElementParent, string p_szCode, string p_szFullCode, string p_szName)
        {
            // Check
            if (string.IsNullOrEmpty(p_szCode) == true)
                return;
            //string l_szX = p_szCode.Substring(0, 3);
            var l_szY = p_szCode.Substring(3, 3);
            // Check Y
            if (
                (string.IsNullOrEmpty(l_szY) == true) ||
                (Convert.ToInt32(l_szY) == 0)
                )
            {
                p_oXElementParent.Add(
                    new XElement("TreeViewItem", 
                        new XAttribute("Header", p_szName),
                        new XAttribute("Code", p_szFullCode)
                        )
                        );
                return;
            }
            // We must move to subNode
            BuildTreeItem(GetXElementFromNodes(p_oXElementParent, p_oXElementParent.Nodes().Count() - 1), p_szCode.Substring(3), p_szFullCode, p_szName);
        }


        /// <summary>
        /// Gets the folder type by organization.
        /// </summary>
        /// <param name="organizationId">The organization id.</param>
        /// <returns></returns>
        public static List<FolderType> GetFolderTypeByOrganization(long organizationId)
        {
            return FolderTypeTranslator.TranslateFolderType(DA_FolderType.GetFolderTypeByOrganization(organizationId));
        }

        /// <summary>
        /// Gets the folder type by id.
        /// </summary>
        /// <param name="folderTypeId">The folder type id.</param>
        /// <returns></returns>
        public static FolderType GetFolderTypeById(long folderTypeId)
        {
            return FolderTypeTranslator.TranslateOneFolderType(DA_FolderType.GetFolderTypeById(folderTypeId));
        }

        /// <summary>
        /// Gets the folder type by user id.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public static List<FolderType> GetFolderTypeByUserId(long userId)
        {
            return FolderTypeTranslator.TranslateFolderType(userId, DA_FolderType.GetFolderTypeByUserId(userId));
        }

        /// <summary>
        /// Deletes a list of organizations.
        /// </summary>
        /// <param name="identifiers">The identifiers.</param>
        /// <returns></returns>
        public static StoredProcedureResultCollection DeactivateFolderTypes(List<long> identifiers)
        {
            StoredProcedureResultCollection result = new StoredProcedureResultCollection();
            foreach (long identifier in identifiers)
            {
                result.Add(DA_FolderType.DeactivateFolderType(identifier));
            }
            return result;
        }

        /// <summary>
        /// Gets the folder type groups.
        /// </summary>
        /// <param name="folderTypeId">The folder type id.</param>
        /// <returns></returns>
        public static List<Group> GetFolderTypeGroups(long folderTypeId)
        {
            return GeneralGroupTranslator.TranslateGroupWithRights(DA_FolderType.GetFolderTypeGroups(folderTypeId));
        }

        /// <summary>
        /// Gets the folder type groups.
        /// </summary>
        /// <param name="groupId">The group id.</param>
        /// <returns></returns>
        public static List<FolderTypeRights> GetFolderTypeRightsByGroupId(long groupId)
        {
            return FolderTypeRightsTranslator.TranslateFolderTypeRights(DA_FolderType.GetFolderTypeRightsByGroupId(groupId));
        }

        /// <summary>
        /// Updates the folder type rank.
        /// </summary>
        /// <param name="sourceId">The source id.</param>
        /// <param name="sourceRank">The source rank.</param>
        /// <param name="destinationId">The destination id.</param>
        /// <param name="destinationRank">The destination rank.</param>
        /// <returns></returns>
        public static bool UpdateFolderTypeRank(long sourceId, int sourceRank, long destinationId, int destinationRank)
        {
            return DA_FolderType.UpdateFolderTypeRank(sourceId, sourceRank, destinationId, destinationRank);
        }

        /// <summary>
        /// Deletes one organization.
        /// </summary>
        /// <param name="identifier">The identifier.</param>
        /// <returns></returns>
        public static StoredProcedureResult DeactivateFolderType(long identifier)
        {
            return DA_FolderType.DeactivateFolderType(identifier);
        }

        /// <summary>
        /// Adds the type of the folder.
        /// </summary>
        /// <param name="organizationIdentifier">The organization identifier.</param>
        /// <param name="name">The name.</param>
        /// <param name="descrition">The descrition.</param>
        /// <param name="groups">The groups.</param>
        /// <param name="natures">The natures.</param>
        /// <returns></returns>
        public static StoredProcedureResult AddFolderType(long organizationIdentifier, string name, string descrition, List<Group> groups, List<long> natures)
        {
            return DA_FolderType.AddFolderType(organizationIdentifier, name, descrition, groups, natures);
        }

        /// <summary>
        /// Adds the type of the folder.
        /// </summary>
        /// <param name="folderType">Type of the folder.</param>
        /// <param name="organizationIdentifier">The organization identifier.</param>
        /// <param name="name">The name.</param>
        /// <param name="descrition">The descrition.</param>
        /// <param name="groups">The groups.</param>
        /// <param name="natures">The natures.</param>
        /// <returns></returns>
        public static StoredProcedureResult UpdateFolderType(long folderType, long organizationIdentifier, string name, string descrition, List<Group> groups, List<long> natures)
        {
            return DA_FolderType.UpdateFolderType(folderType, organizationIdentifier, name, descrition, groups, natures);
        }

    }
}
